package com.lili.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lili.config.cache.RedisCache;
import com.lili.mapper.*;
import com.lili.pojo.*;
import com.lili.service.*;
import com.lili.vo.request.troop.QueryReqVO;
import com.lili.vo.request.officer.ToMarkExamReqVO;
import com.lili.vo.response.other.KeyValue;
import com.lili.vo.response.troop.*;
import com.lili.vo.response.officer.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Service
public class ExamRecordServiceImpl extends ServiceImpl<ExamRecordMapper, ExamRecord>
        implements ExamRecordService {

    private ExamRecordMapper examRecordMapper;
    private ExamMapper examMapper;
    private ExamQuestionAnswerMapper examQuestionAnswerMapper;
    private WrongService wrongService;
    private RedisCache redisCache;

    @Autowired
    public ExamRecordServiceImpl(ExamRecordMapper examRecordMapper, ExamMapper examMapper,
                                 ExamQuestionAnswerMapper examQuestionAnswerMapper,
                                 WrongService wrongService, RedisCache redisCache) {
        this.examRecordMapper = examRecordMapper;
        this.examMapper = examMapper;
        this.examQuestionAnswerMapper = examQuestionAnswerMapper;
        this.wrongService = wrongService;
        this.redisCache = redisCache;
    }

    @Override
    public IPage<RecordRespVO> selectPageList(QueryReqVO vo) {
        IPage<RecordRespVO> page = new Page<>(vo.getPageIndex(), vo.getPageSize());
        IPage<RecordRespVO> pages = baseMapper.selectPageList(page, vo);
        return pages;
    }


    /**
     * 有缓存
     * 得到考核记录已经考过的试卷
     *
     * @param examId
     * @param userId
     * @return
     */
    @Override
    public ExamViewVO selectExamView(Integer examId, Integer userId) {
        String key = "exam:" + examId + "-user:" + userId;
        ExamViewVO vo = new ExamViewVO();
        Object obj = redisCache.getCacheObject(key);
        if (!Objects.isNull(obj)) {
            vo = (ExamViewVO) obj;
            return vo;
        }
        // 查询records中的数据
        LambdaQueryWrapper<ExamRecord> recordWrapper = new LambdaQueryWrapper<>();
        recordWrapper.eq(ExamRecord::getExamId, examId)
                .eq(ExamRecord::getCreateUser, userId);
        ExamRecord record = examRecordMapper.selectOne(recordWrapper);
        vo.setExamId(record.getExamId());
        vo.setDoTime(record.getDoTime());
        vo.setTotalScore(record.getTotalScore());
        vo.setIscorrected(record.getIscorrected());

        //查询exam的数据
        Exam exam = examMapper.selectById(record.getExamId());
        vo.setExamName(exam.getExamName());
        vo.setExamTotal(exam.getExamTotal());

        //查询作答项
        List<ExamViewAnswerItem> answerItems = examQuestionAnswerMapper.selectExamViewList(userId, examId);
        vo.setAnswers(answerItems);

        //设置缓存
        redisCache.setCacheObject(key, vo, 10, TimeUnit.MINUTES);

        return vo;
    }

    @Override
    public List<ScoreDetailRespVO> selectScoreList(Integer examId, Integer classesId) {
        AtomicInteger rank = new AtomicInteger(1);
        List<ScoreDetailRespVO> vos = baseMapper.selectScoreList(examId, classesId).stream().map(item -> {
            item.setRank(rank.getAndIncrement());
            return item;
        }).collect(Collectors.toList());
        return vos;
    }


    @Override
    public IPage<ToMarExamRecordRespVO> selectToMarkPageList(ToMarkExamReqVO vo) {
        IPage<ToMarExamRecordRespVO> page = new Page<>(vo.getPageIndex(), vo.getPageSize());
        return baseMapper.selectMarkPageList(page, vo);
    }

    /**
     * @param user
     * @return
     */
    @Override
    public ChartVO selectIndexChart(User user) {
        List<KeyValue> list = baseMapper.selectKVS(user);
        ChartVO vo = new ChartVO();
        List<String> xData = new ArrayList<>();
        List<Integer> yData = new ArrayList<>();
        list.forEach(item -> {
            xData.add(item.getName());
            yData.add(item.getValue());
        });
        vo.setXdata(xData);
        vo.setYdata(yData);
        return vo;
    }

    /**
     * 根据ID查询到待批改试卷的作答情况
     *
     * @param id
     */
    @Override
    @Transactional(readOnly = true, rollbackFor = RuntimeException.class)
    public ExamViewVO selectRecordById(Integer id) {
        ExamViewVO vo = new ExamViewVO();
        //得到Record的数据
        ExamRecord record = baseMapper.selectById(id);
        //根据Record中examId得到试卷中的数据
        Exam exam = examMapper.selectById(record.getExamId());
        vo.setExamName(exam.getExamName());
        List<ExamViewAnswerItem> examViewAnswerItems = examQuestionAnswerMapper.selectExamViewList(record.getCreateUser(), exam.getId());
        vo.setAnswers(examViewAnswerItems);
        return vo;
    }

    /**
     * 军官对试卷进行批改
     *
     * @param vo
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void correct(ExamViewVO vo) {
        ExamRecord examRecord = baseMapper.selectById(vo.getExamId());
        examRecord.setIscorrected(1);
        List<ExamViewAnswerItem> answers = vo.getAnswers();
        double scoreNum=0;
        for (ExamViewAnswerItem item:answers){
            scoreNum=scoreNum+item.getScore();
        }
        examRecord.setTotalScore(scoreNum);
        this.getBaseMapper().updateById(examRecord);
    }

    private Wrong getWrong(ExamQuestionAnswer questionAnswer, Exam exam, Integer createUser) {
        Wrong wrong = new Wrong();
        wrong.setQuestionId(questionAnswer.getQuestionId());
        wrong.setSubjectId(exam.getSubjectId());
        wrong.setCreateUser(createUser);
        wrong.setAnswer(questionAnswer.getAnswer());
        return wrong;
    }
}




